Scroll to navigation

SHMGET(2) Руководство программиста Linux SHMGET(2)

ИМЯ

shmget - выделяет общий сегмент памяти

ОБЗОР

#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

ОПИСАНИЕ

Вызов shmget() возвращает идентификатор общего сегмента памяти, соответствующего значению аргумента key. Если значение key равно IPC_PRIVATE или если key не равно IPC_PRIVATE, но не существует общего сегмента памяти, который бы соответствовал значению key и в shmflg есть флаг IPC_CREAT, то создаётся новый общий сегмент памяти размером size, округлённым до значения, кратного PAGE_SIZE.

Если в shmflg одновременно указаны IPC_CREAT и IPC_EXCL и для значения key уже существует общий сегмент памяти, то вызов shmget() завершается с ошибкой и errno присваивается EEXIST (такой же результат как с O_CREAT | O_EXCL у open(2)).

Значение shmflg составляется из следующих флагов:

Служит для создания нового сегмента. Если этого флага нет, то вызов shmget() будет искать сегмент, соответствующий key, и затем проверит, имеет ли пользователь права на доступ к сегменту.
Используется совместно с IPC_CREAT для того, чтобы отказаться от создания при наличии сегмента.
В младших 9 битах задаются права для владельца, группы и всех остальных. Формат значения совпадает с аргументом mode вызова open(2). В данный момент бит выполнения системой не используются.
Выделять сегмент используя «огромные страницы». Дополнительную информацию смотрите в файле исходного кода ядра Documentation/vm/hugetlbpage.txt.
Этот флаг нужен для того же, что и флаг MAP_NORESERVE у mmap(2). Он указывает не резервировать место в пространстве подкачки для этого сегмента. Операцией резервирования места в пространстве подкачки гарантируется, что сегмент можно изменить. Если место не резервировать, то при записи можно получить сигнал SIGSEGV, если кончится физическая память. Смотрите также обсуждение файла /proc/sys/vm/overcommit_memory в proc(5).

Если создаётся новый общий сегмент памяти, то его содержимое инициализируется нулями, а соответствующая ему структура данных shmid_ds (см. shmctl(2)) следующим образом:

Полям shm_perm.cuid и shm_perm.uid присваиваются значения эффективного идентификатора пользователя вызывающего процесса.
Полям shm_perm.cgid и shm_perm.gid присваиваются значения эффективного идентификатора группы вызывающего процесса.
Младшим 9 битам shm_perm.mode присваивается значение младших 9 бит shmflg.
Полю shm_segsz присваивается значение size.
Полям shm_lpid, shm_nattch, shm_atime и shm_dtime присваивается 0.
Полю shm_ctime присваивается значение текущего времени.

Если общий сегмент памяти уже существует, то проверяются права доступа к нему и не помечен ли он для удаления.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении возвращается корректный идентификатор сегмента shmid и -1 в случае ошибки.

ОШИБКИ

В случае возникновения ошибки errno может принимать следующие значения:

Пользователь не имеет прав доступа к общему сегменту памяти и не имеет мандата CAP_IPC_OWNER.
Указан флаг IPC_CREAT | IPC_EXCL и сегмент существует.
Был создан новый сегмент и size < SHMMIN или size > SHMMAX, или новый сегмент не создан, т.к. существует сегмент с указанным ключом, но size больше размера этого сегмента.
Достигнуто максимальное количество открытых файлов в системе.
Не существует сегмента для ключа key и флаг IPC_CREAT не указан.
Не хватает памяти для выделения под перерасход сегмента.
Все возможные идентификаторы сегментов уже распределены (SHMMNI) или размер выделяемого сегмента превысит системные лимиты по общей памяти (SHMALL).
Указан флаг SHM_HUGETLB, но у вызывающего нет прав (нет мандата CAP_IPC_LOCK).

СООТВЕТСТВИЕ СТАНДАРТАМ

SVr4, POSIX.1-2001.

Флаг SHM_HUGETLB является непереносимым расширением Linux.

ЗАМЕЧАНИЯ

Включение файлов <sys/types.h> и <sys/ipc.h> не требуется в Linux или любых версий POSIX. Однако, некоторые старые реализации требуют включения данных заголовочных файлов, и это также требуется по SVID. В приложениях, которые нужно перенести на такие старые системы, может потребоваться включить данных заголовочные файлы.

IPC_PRIVATE не поле флага, а тип key_t. Если key равно этому значению, то системный вызов игнорирует всё кроме 9-ти младших битов shmflg и создаёт новый общий сегмента памяти (при успешном выполнении).

Ниже приведены лимиты ресурсов на общий сегмент памяти, влияющие на вызов shmget():

Максимальное количество страниц общей памяти в системе (в Linux это ограничение можно получить и изменить через /proc/sys/kernel/shmall).
Максимальный размер общего сегмента памяти в байтах в системе: зависит от политики (в Linux это ограничение можно получить и изменить через /proc/sys/kernel/shmmax).
Минимальный размер общего сегмента памяти в байтах в системе: зависит от реализации (в настоящий момент равно 1 байту, хотя на самом деле минимальный выделяемый размер равен PAGE_SIZE).
Максимальное количество сегментов общей памяти в системе: зависит от реализации (в настоящий момент — 4096, до Linux 2.3.99 было равно 128; в Linux это ограничение можно получить и изменить через /proc/sys/kernel/shmmni).

Реализацией не ограничивается максимальное количество общих сегментов памяти на процесс (SHMSEG).

Замечания, касающиеся Linux

В Linux до версии 2.3.30 вызов shmget() возвращал значение EIDRM, если общий сегмент памяти был запланирован к удалению.

ДЕФЕКТЫ

Имя IPC_PRIVATE, возможно, было выбрано неудачно, IPC_NEW отражает смысл действия более ясно.

СМОТРИТЕ ТАКЖЕ

shmat(2), shmctl(2), shmdt(2), ftok(3), capabilities(7), shm_overview(7), svipc(7)

2012-05-31 Linux